#pragma once
#include <iostream>
#include <string>
#include "exchange.hpp"
#include "binding.hpp"
#include "message.hpp"
#include "queue.hpp"
#include <google/protobuf/map.h>
namespace ns_rabbitmq
{
    class VirtualHost
    {
    public:
        VirtualHost(const std::string &host_name, const std::string &basedir, const std::string &dbfile)
            : _host_name(host_name),
              _exchangeptr(std::make_shared<ExchangeManager>(dbfile)), _queueptr(std::make_shared<QueueManager>(dbfile)),
              _bindptr(std::make_shared<BindManager>(dbfile)), _msgptr(std::make_shared<MessageManager>(basedir))
        {
            // 交换机/队列/绑定会进行数据恢复
            MsgQueMap quemap = _queueptr->AllQueues();
            for (auto &que : quemap)
            {
                _msgptr->InitQueueMsg(que.first);
            }
        }

        // 声明交换机
        bool DeclareExchange(const std::string &ename, ExchangeType exchangetype,
                             bool durable, bool autodelete, const google::protobuf::Map<std::string, std::string> &args)
        {

            bool ret = _exchangeptr->DeclareExchange(ename, exchangetype, durable, autodelete, args);
            if (!ret)
            {
                DLOG("声明交换机%s失败", ename.c_str());
                return false;
            }

            return true;
        }
        // 移除交换机,同时解除绑定
        void DeleteExchange(const std::string &ename)
        {
            _bindptr->RemoveExchangeBindings(ename);
            _exchangeptr->DeleteExchange(ename);
        }

        ExchangeMachine::MachinePtr SelectExchange(const std::string &ename)
        {
            return _exchangeptr->SelectExchange(ename);
        }

        bool IsExchangeExists(const std::string &ename)
        {
            return _exchangeptr->IsExistsMachine(ename);
        }

        // 声明队列1.消息的初始化 2.声明
        bool DeclareQueue(const std::string &qname, bool exclusive,
                          bool durable, bool auto_delete, const google::protobuf::Map<std::string, std::string> &args)
        {
            _msgptr->InitQueueMsg(qname);
           return  _queueptr->DeclareQueue(qname, exclusive, durable, auto_delete, args);
        }
        // 移除队列 1.消息的移除 2.解除绑定关系
        void DeleteQueue(const std::string &qname)
        {
            _msgptr->DestoryQueueMsg(qname);
            _bindptr->RemoveQueueBinding(qname);
            _queueptr->DeleteQueue(qname);
        }

        MsgQueuePtr SelectQueue(const std::string &qname)
        {
            return _queueptr->SelectQueue(qname);
        }

        bool IsQueueExists(const std::string &qname)
        {
            return _queueptr->IsExistsQueue(qname);
        }

        // 获取交换机是否持久化
        bool Bind(const std::string &exchange_name, const std::string &queue_name, const std::string &binding_key, bool durable)
        {
            ExchangeMachine::MachinePtr exchange = SelectExchange(exchange_name);
            if (!exchange.get())
            {
                DLOG("交换机%s不存在!", exchange_name.c_str());
                return false;
            }
            MsgQueuePtr queue = SelectQueue(queue_name);
            if (!queue.get())
            {
                DLOG("队列%s不存在!", queue_name.c_str());
                return false;
            }
            return _bindptr->Bind(exchange_name, queue_name, binding_key, durable && exchange->_durable && queue->_durable);
        }

        void UnBind(const std::string &exchange_name, const std::string &queue_name)
        {
            _bindptr->UnBind(exchange_name, queue_name);
        }

        // 获取交换机的所有绑定队列
        QueueMap GetExchangeBindings(const std::string &exchange_name)
        {
            return _bindptr->GetExchangeBindings(exchange_name);
        }

        bool IsBindExists(const std::string &ename, const std::string &qname)
        {
            return _bindptr->IsExistsBinding(ename, qname);
        }

        bool BasicPublish(const std::string &qname, BasicProperties *bp, const std::string &body)
        {
            MsgQueuePtr queue =_queueptr->SelectQueue(qname);
            if (!queue.get())
            {
                DLOG("队列%s不存在!", qname.c_str());
                return false;
            }
            return _msgptr->Insert(qname, bp, body, queue->_durable);
        }

        MessagePtr BasicConsume(const std::string &qname)
        {
            return _msgptr->Front(qname);
        }

        void Ack(const std::string &qname, const std::string &msg_id)
        {
            return _msgptr->ack(qname, msg_id);
        }

        MsgQueMap AllQueues()
        {
            return _queueptr->AllQueues();
        }
    private:
        std::string _host_name;
        ExchangeManager::ExchangeManagerPtr _exchangeptr;
        QueueManager::QueueManagerPtr _queueptr;
        BindManager::BindingManagePtr _bindptr;
        MessageManager::MessageManagerPtr _msgptr;
    };
    using HostPtr = std::shared_ptr<VirtualHost>;
}